use crate::IResult;


/// 空格
pub const SPACE: u8 = ' ' as u8;
/// 换行符\n
pub const LINE: u8 = '\n' as u8;
/// 回车符\r
pub const ENTER: u8 = '\r' as u8;
/// 制表符\t
pub const TAB: u8 = '\t' as u8;
/// 逗号
pub const COMMA: u8 = ',' as u8;
/// 分号
pub const SEMICOLON: u8 = ';' as u8;
/// 冒号
pub const COLON: u8 = ':' as u8;


pub fn to_print(chrs: &[u8]) -> String {
    if chrs.len() == 0 {
        return "[]".to_string();
    }
    let mut buf = format!("[{}", chrs[0]);
    for index in 1..chrs.len() {
        buf.push(',');
        buf.push(chrs[index] as char);
    }
    buf.push(']');
    buf
}

#[test]
fn test_to_print() {
    let chrs = vec![SPACE, LINE, ENTER, TAB, COMMA, SEMICOLON, COLON];
    println!("chrs={}", to_print(&chrs));
}

pub fn trim_left(content: &str, chrs: &[u8]) -> IResult<String> {
    if chrs.len() == 0 {
        return Ok(content.to_string());
    }
    let mut bytes = content.to_string().into_bytes();
    loop {
        if bytes.len() == 0 {
            return Ok("".to_string());
        }
        if chrs.contains(&bytes[0]) {
            bytes.remove(0);
        } else {
            break;
        }
    }
    match String::from_utf8(bytes) {
        Ok(v) => Ok(v),
        Err(e) => {
            let split = to_print(chrs);
            Err(format!("string_ex::trim_left error: ({content}, {split}), {e:?}").as_str())?
        },
    }
    
}

pub fn trim_right(content: &str, chrs: &[u8]) -> IResult<String> {
    if chrs.len() == 0 {
        return Ok(content.to_string());
    }
    let mut bytes = content.to_string().into_bytes();
    if bytes.len() == 0 {
        return Ok("".to_string());
    }
    let mut index = bytes.len() - 1;
    loop {
        if chrs.contains(&bytes[index]) {
            bytes.remove(index);
            if index == 0 {
                return Ok("".to_string());
            }
            index -= 1;
        } else {
            break;
        }
    }
    match String::from_utf8(bytes) {
        Ok(v) => Ok(v),
        Err(e) => {
            let split = to_print(chrs);
            Err(format!("string_ex::trim_left error: ({content}, {split}), {e:?}").as_str())?
        },
    }
    
}

pub fn trim(content: &str, chrs: &[u8]) -> IResult<String> {
    // 基本判断
    if chrs.len() == 0 {
        return Ok(content.to_string());
    }
    let mut bytes = content.to_string().into_bytes();
    if bytes.len() == 0 {
        return Ok("".to_string());
    }
    // 右侧
    let mut index = bytes.len() - 1;
    loop {
        if chrs.contains(&bytes[index]) {
            bytes.remove(index);
            if index == 0 {
                return Ok("".to_string());
            }
            index -= 1;
        } else {
            break;
        }
    }
    // 左侧
    loop {
        if bytes.len() == 0 {
            return Ok("".to_string());
        }
        if chrs.contains(&bytes[0]) {
            bytes.remove(0);
        } else {
            break;
        }
    }
    // 剩下部分
    match String::from_utf8(bytes) {
        Ok(v) => Ok(v),
        Err(e) => {
            let split = to_print(chrs);
            Err(format!("string_ex::trim_left error: ({content}, {split}), {e:?}").as_str())?
        },
    }
    
}

#[test]
fn test_trim_left() {
    let chrs = vec![SPACE, COMMA];
    let a = trim_left("   , ", &chrs).unwrap();
    println!("a={a}=a");
    let a = trim_left(" , hl  ", &chrs).unwrap();
    println!("a={a}=a");
}

#[test]
fn test_trim_right() {
    let chrs = vec![SPACE, COMMA];
    let a = trim_right("   , ", &chrs).unwrap();
    println!("a={a}=a");
    let a = trim_right(" , hl  ", &chrs).unwrap();
    println!("a={a}=a");
    let a = trim_right(" , hl   , ", &chrs).unwrap();
    println!("a={a}=a");
}

pub fn split(content: &str, bt_split: u8, remove_empty: bool) -> IResult<Vec<String>> {
    let mut items = vec![];
    let bytes = content.to_string().into_bytes();
    
    let mut bytes_sub = vec![];
    for bt in bytes {
        if bt_split == bt {
            if bytes_sub.len() == 0 {
                if !remove_empty {
                    items.push("".to_string());
                }
            } else {
                match String::from_utf8(bytes_sub.clone()) {
                    Ok(v) => items.push(v),
                    Err(e) => {
                        let split = bt_split as char;
                        return Err(format!("string_ex::split error: ({content}, {split}), {e:?}").as_str())?;
                    },
                };
            }
            bytes_sub.clear();
        } else {
            bytes_sub.push(bt);
        }
    }


    if bytes_sub.len() == 0 {
        if !remove_empty {
            items.push("".to_string());
        }
    } else {
        match String::from_utf8(bytes_sub.clone()) {
            Ok(v) => items.push(v),
            Err(e) => {
                let split = bt_split as char;
                return Err(format!("string_ex::split error: ({content}, {split}), {e:?}").as_str())?;
            },
        };
    }



    Ok(items)
}

pub fn split_m(content: &str, chrs: &[u8], remove_empty: bool) -> IResult<Vec<String>> {
    let mut items = vec![];
    let bytes = content.to_string().into_bytes();
    
    let mut bytes_sub = vec![];
    for bt in bytes {
        if chrs.contains(&bt) {
            if bytes_sub.len() == 0 {
                if !remove_empty {
                    items.push("".to_string());
                }
            } else {
                match String::from_utf8(bytes_sub.clone()) {
                    Ok(v) => items.push(v),
                    Err(e) => {
                        let split = to_print(chrs);
                        return Err(format!("string_ex::split error: ({content}, {split}), {e:?}").as_str())?;
                    },
                };
            }
            bytes_sub.clear();
        } else {
            bytes_sub.push(bt);
        }
    }


    if bytes_sub.len() == 0 {
        if !remove_empty {
            items.push("".to_string());
        }
    } else {
        match String::from_utf8(bytes_sub.clone()) {
            Ok(v) => items.push(v),
            Err(e) => {
                let split = to_print(chrs);
                return Err(format!("string_ex::split error: ({content}, {split}), {e:?}").as_str())?;
            },
        };
    }



    Ok(items)
}


#[test]
fn test_split() {
    let chrs = vec![SPACE];
    let a = split_m("   , ", &chrs, true).unwrap();
    println!("a={a:?}");
    let a = split_m("   , ", &chrs, false).unwrap();
    println!("b={a:?}");

    let chrs = vec![COMMA];
    let a = split_m("   , ", &chrs, true).unwrap();
    println!("c={a:?}");
    let a = split_m("   , ", &chrs, false).unwrap();
    println!("d={a:?}");


}
